﻿using System;
using System.Windows.Forms;
using ff14bot.Behavior;
using ff14bot.Enums;
using ff14bot.Managers;
using System.Linq;
using TreeSharp;
using Magitek.Helpers;
using ff14bot;
using Action = TreeSharp.Action;
using ff14bot.Objects;

namespace Magitek.Rotations
{
    public class Bard : Magitek
    {
		public SpellData SkillBlocker;
        public override float PullRange { get { return WindowSettings.BardPullRange; } }
        public override ClassJobType[] Class { get { return new ClassJobType[] { ClassJobType.Bard }; } }
        public override void OnPulse()
        {
			if(Core.Me.InCombat)
				Actionmanager.CurrentActions.TryGetValue("Heavy Shot", out SkillBlocker);
			if (!Core.Me.InCombat)
				{
                if (Actionmanager.CanCast("Swiftsong", Core.Me) && !Core.Me.HasAura("Swiftsong") && !MovementManager.IsMoving && WindowSettings.BardUseSwiftsong)
                    Actionmanager.DoAction("Swiftsong", Core.Me);
				}
        }
        #region Pulling & Resting
        protected override Composite CreatePull()
        {
            return Combat.CreatePull(PullRange);
        }
        protected override Composite CreateRest()
        {
            return Extensions.DefaultRestBehavior(r => Core.Player.CurrentManaPercent);
        }
        #endregion
        #region Buffs // Mainly used for Grindbot etc...

        protected override Composite CreatePreCombatBuffs()
        {
            return new PrioritySelector(
                Extensions.SummonChocobo()
                );
        }

        protected override Composite CreateCombatBuffs()
        {
                return new PrioritySelector(
                new Decorator(r => Core.Player.CurrentTarget.CurrentHealth >= WindowSettings.BardTargetHPBelowToUseBuffs, new PrioritySelector(
                Casting.Cast(r => "Internal Release", r => WindowSettings.BardUseBuffs && WindowSettings.BardUseInternalRelease && (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player, r => 0, r => false),
                Casting.Cast(r => "Raging Strikes", r => WindowSettings.BardUseBuffs && WindowSettings.BardUseRagingStrikes && (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player, r => 0, r => false),
                Casting.Cast(r => "Hawk's Eye", r => WindowSettings.BardUseBuffs && WindowSettings.BardUseHawksEye && (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player, r => 0, r => false),
                Casting.Cast(r => "Barrage", r => WindowSettings.BardUseBuffs && WindowSettings.BardUseBarrage && (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player, r => 0, r => false),
                Casting.Cast(r => "Blood for Blood", r => WindowSettings.BardUseBuffs && WindowSettings.BardUseBloodForBlood && (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player, r => 0, r => false),
				Casting.Cast(r => "Quelling Strikes", r => WindowSettings.BardUseBuffs && WindowSettings.BardUseQuellingStrikes && (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player, r => 0, r => false))));
        }

        #endregion
        #region Bard Helpers

        private Composite MagesBallad()
        {

            return new Action(ret =>
            {

                if (PartyManager.IsInParty && WindowSettings.BardUseMagesBallad && !Extensions.DoubleCastPreventionDict.Contains(Core.Player, "Mage's Ballad") && !Core.Player.HasAura("Mage's Ballad"))
                {
                    if (PartyManager.VisibleMembers.Where(
                        u => (u.GameObject as BattleCharacter).CurrentManaPercent <= WindowSettings.BardStartMagesBalladMp &&
                             (u.Class == ClassJobType.WhiteMage || u.Class == ClassJobType.Scholar)).Any())
                    {

                        Actionmanager.DoAction("Mage's Ballad", Core.Player);
                        Extensions.UpdateDoubleCastDict("Mage's Ballad", Core.Player);

                    }
                }

                return RunStatus.Failure;

            });

        }

        private bool MaxDots()
        {
            if ((Core.Player.CurrentTarget as BattleCharacter).CharacterAuras.Count() >= 30) 
                return true;

            return false;
        }

        private Composite ArmysPaeon()
        {
            return new Action(ret =>
            {

                if (PartyManager.IsInParty && WindowSettings.BardUseArmysPaeon && Core.Player.CurrentManaPercent > WindowSettings.BardStopAnythingButMagesBallad && !Extensions.DoubleCastPreventionDict.Contains(Core.Player, "Army's Paeon") && (!Core.Player.HasAura("Army's Paeon") || !Core.Player.HasAura("Mage's Ballad", true)))
                {
                    if (PartyManager.VisibleMembers.Where(
                        u => (u.GameObject as BattleCharacter).CurrentTPPercent <= WindowSettings.BardStartArmysPaeonTp).Any())
                    {

                        Actionmanager.DoAction("Army's Paeon", Core.Player);
                        Extensions.UpdateDoubleCastDict("Army's Paeon", Core.Player);

                    }
                }

                if (PartyManager.IsInParty && WindowSettings.BardUseArmysPaeon && Core.Player.CurrentManaPercent <= WindowSettings.BardStopAnythingButMagesBallad && Core.Player.HasAura("Army's Paeon", true))
                {
                        Actionmanager.DoAction("Army's Paeon", Core.Player);
                }

                return RunStatus.Failure;

            });
        }

        private Composite FoeRequiem()
        {
            return new Action(ret =>
            {

                if (PartyManager.IsInParty && WindowSettings.BardUseFoeRequieum && Core.Player.CurrentManaPercent > WindowSettings.BardStopAnythingButMagesBallad && !Extensions.DoubleCastPreventionDict.Contains(Core.Player, "Foe Requiem") && (!Core.Player.HasAura("Foe Requiem") || !Core.Player.HasAura("Mage's Ballad", true)))
                {
                    if (PartyManager.VisibleMembers.Where(
                        u => u.Class == ClassJobType.Summoner || u.Class == ClassJobType.BlackMage).Any())
                    {

                        Actionmanager.DoAction("Foe Requiem", Core.Player);
                        Extensions.UpdateDoubleCastDict("Foe Requiem", Core.Player);

                    }
                }

                if (PartyManager.IsInParty && WindowSettings.BardUseFoeRequieum && Core.Player.CurrentManaPercent <= WindowSettings.BardStopAnythingButMagesBallad && Core.Player.HasAura("Foe Requiem", true))
                {
                    Actionmanager.DoAction("Foe Requiem", Core.Player);
                }

                return RunStatus.Failure;

            });
        }

        #endregion
        #region Combat
        public override Composite OnTreeSharpPulse()
        {
            return new PrioritySelector(
				Items.Use(WindowSettings.foodname, true),
                new Decorator(r => Core.Player.InCombat || Core.Player.IsDead || Core.Player.IsMounted || !Core.Player.IsValid, new ActionAlwaysSucceed()),
                    Casting.Cast(r => "Swiftsong", r => WindowSettings.BardUseSwiftsong && !Core.Player.HasAura("Swiftsong"), r => Core.Player, r => 3, r => true));
        }
        protected override Composite CreateCombat()
        {
	            return new PrioritySelector(ctx => Core.Player.CurrentTarget,
                new Decorator(ctx => ctx != null,
                new PrioritySelector(
                new Decorator(r => BotManager.Current.IsAutonomous, new PrioritySelector(
                CommonBehaviors.MoveToLos(ctx => ctx as GameObject),
                CommonBehaviors.MoveAndStop(ctx => (ctx as GameObject).Location, ctx => 24, true, "[Magitek] Moving in Range"))),

				Casting.Cast(r => "Blunt Arrow", r => WindowSettings.InterruptCast && Combat.CheckForInterrupt(), r => Core.Player.CurrentTarget, r => 1, r => false),
                Defensive,
                Combat.DoPVP(),
                SingASong,
                new Decorator(r => WindowSettings.AOEEnabled, new PrioritySelector(AOE)),
                StraightShot,
                AOE,
				SingleTargetRotation,
				FlamingArrow,
				Insta
                

				

            )));
        }

        public Composite SingleTargetRotation
        {
            get
            {
                return new PrioritySelector(
                Casting.Cast(r => "Windbite", r => !MaxDots() && !Core.Player.CurrentTarget.HasAura("Windbite", true) && (Core.Player.CurrentTarget as BattleCharacter).CurrentHealth >= WindowSettings.BardUseWindbiteAbove, r => Core.Player.CurrentTarget, r => 1, r => false),
                Casting.Cast(r => "Venomous Bite", r => !MaxDots() && !Core.Player.CurrentTarget.HasAura("Venomous Bite", true) && (Core.Player.CurrentTarget as BattleCharacter).CurrentHealth >= WindowSettings.BardUseVenomousAbove && !WindowSettings._bardDontVenomousList.Contains(Core.Player.CurrentTarget.Name), r => Core.Player.CurrentTarget, r => 1, r => false),
				Casting.Cast(r => "Straight Shot", r => Core.Player.HasAura("Straighter Shot"), r => Core.Player.CurrentTarget, r => 1, r => false),
                Casting.Cast(r => "Heavy Shot", r => true, r => Core.Player.CurrentTarget, r => 1, r => false));
            }
        }


        public Composite FlamingArrow
        {
            get
            {
                return
                    new Decorator(r => WindowSettings.BardUseFlamingArrow && Actionmanager.CanCast("Flaming Arrow", Core.Player.CurrentTarget) && (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50),
                                new Action(r => Actionmanager.DoActionLocation("Flaming Arrow", Core.Target.Location)));
            }
        }

        public Composite Insta
        {
            get
            {
                return new PrioritySelector(
                    Casting.Cast(r => "Misery's End", r => (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player.CurrentTarget, r => 1, r => false),
                    Casting.Cast(r => "Bloodletter", r => (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player.CurrentTarget, r => 1, r => false),
					Casting.Cast(r => "Blunt Arrow", r => !WindowSettings.InterruptCast && (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player.CurrentTarget, r => 1, r => false),
					Casting.Cast(r => "Repelling Shot", r => Core.Player.CurrentTarget.Location.Distance(Core.Player.Location) < 5 && WindowSettings.BardUseRepellingShot && (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player.CurrentTarget, r => 1, r => false));
					
            }
        }

        public Composite Defensive
        {
            get
            {
                return new PrioritySelector(
                    Casting.Cast(r => "Second Wind", r => Core.Player.CurrentHealthPercent <= WindowSettings.BardUseSecondWindHp && (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player, r => 1, r => false),
                    Casting.Cast(r => "Featherfoot", r => Core.Player.CurrentHealthPercent <= WindowSettings.BardUseFeatherFootHp && (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player, r => 1, r => false),
                    Casting.Cast(r => "Invigorate", r => Core.Player.CurrentTPPercent <= WindowSettings.BardUseInvigorateTp && (SkillBlocker.Cooldown.TotalMilliseconds >= 1000 || Core.Player.CurrentTP <= 50), r => Core.Player, r => 1, r => false));
            }
        }

        public Composite AOE
        {
            get
            {
                return new PrioritySelector(
                Casting.Cast(r => "Quick Nock", r => (WindowSettings.BardUseAOE && Core.Player.HasAura("Quicker Nock") && Extensions.EnemiesNearTarget(12) >= WindowSettings.TargetsToAOE && Core.Player.CurrentTPPercent > WindowSettings.BardStopAOETp && !WindowSettings._dontaoeList.Contains(Core.Player.CurrentTarget.Name)) || (Core.Player.HasAura("Quicker Nock") && WindowSettings.AOEEnabled), r => Core.Player.CurrentTarget, r => 1, r => false),
                Casting.Cast(r => "Rain of Death", r => (WindowSettings.BardUseAOE && Core.Player.HasAura("Downpour of Death") && Extensions.EnemiesNearTarget(8) >= WindowSettings.TargetsToAOE && Core.Player.CurrentTPPercent > WindowSettings.BardStopAOETp && !WindowSettings._dontaoeList.Contains(Core.Player.CurrentTarget.Name)) || (Core.Player.HasAura("Downpour of Death") && WindowSettings.AOEEnabled), r => Core.Player.CurrentTarget, r => 1, r => false),
                Casting.Cast(r => "Wide Volley", r => (WindowSettings.BardUseAOE && Extensions.EnemiesNearTarget(5) >= WindowSettings.TargetsToAOE && !WindowSettings._dontaoeList.Contains(Core.Player.CurrentTarget.Name)) || (WindowSettings.AOEEnabled), r => Core.Player.CurrentTarget, r => 1, r => false));				
            }
        }

        public Composite StraightShot
        {
            get { return Casting.Cast(r => "Straight Shot", r => !Core.Player.HasAura("Straight Shot"), r => Core.Player.CurrentTarget, r => 0, r => false); }
        }

        public Composite SingASong
        {
            get
            {
                return new PrioritySelector( 
                    MagesBallad(),
                    ArmysPaeon(),
                    FoeRequiem());
            }
        }
        #endregion
    }
}
